package scfg.utils;

import java.util.*;
import java.io.*;

import scfg.output.Display;
import desposito6.datastructures.PriorityDeque;
import desposito6.utils.CommandLine;

public class SortFileFormatter {

	private static Display output;

	static {
		output = new Display("SortFileFormatter");
	}

	public static PriorityDeque<SortableScoredFile> processFile(File f, PriorityDeque<SortableScoredFile> filenames) {
		if (f == null || !f.exists() || f.isDirectory())
			return null;

		try {
			Scanner scan = new Scanner(f);
			StringBuilder sb;
			while (scan.hasNextLine()) {
				sb = new StringBuilder();
				String nextLine = scan.nextLine();
				if (nextLine.matches("\\d+\\s*(/(.|\\w)+)+")) {
					String[] line = nextLine.split("\\s");
					String num = Display.buf(line[0],
							MFECategorizer.BUFFER, '0');
					line = line[1].split("/");
					if (!line[line.length - 1].matches("\\d+_.+")) {
						line[line.length - 1] = num + "_"
								+ line[line.length - 1];
					}
					for (String s : line)
						if (s.length() > 0)
							sb.append("/" + s);
					filenames.insert(new SortableScoredFile(new File(sb.toString()), num));
					output.out(sb.toString());
				}
			}
			return filenames;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void processDir(String filename) {
		processDir(new File(filename), new PriorityDeque<SortableScoredFile>());
	}

	public static PriorityDeque<SortableScoredFile> processDir(File base, PriorityDeque<SortableScoredFile> filenames) {
		if (base == null || !base.exists() || !base.isDirectory())
			return null;
		output.console("Opening " + base.getAbsolutePath());
		File[] files = base.listFiles();
		Stack<File> dirs = new Stack<File>();
		for (File f : files) {
			if (f.isDirectory() && f.getName().charAt(0) != '.')
				dirs.push(f);
			else if (f.getName().endsWith("_sort.txt"))
				filenames = processFile(f, filenames);
		}
		while (!dirs.isEmpty())
			filenames = processDir(dirs.pop(), filenames);
		return filenames;
	}

	private static void writeListFile(String filename,
			List<SortableScoredFile> list) {
		Display o = new Display(filename, null, false);
		for (SortableScoredFile sf : list)
			o.out(sf.getAbsolutePath());
		o.finalizeDisplay();
	}

	public static String helpMessage() {
		return "\n[scfg.utils.StructureAggregator]\n\t"
				+ "* -h Display help message.\n\t"
				+ "* -s Source file.\n\t"
				+ "* -min Get the defined number of files from the smallest values.\n\t"
				+ "* -max Get the defined number of files from the largest values.\n\t"
				+ "* -group Get groups with the defined number of files.\n\t"
				+ "* -delete Delete the old file. (Optional) - Not implemented.\n\t"
				+ "* -v Display verbose output. (Optional)\n\n";
	}

	/**
	 * <pre>
	 * -h Display help message.
	 * -s Source folder.
	 * -delete Delete old file. (Optional) - Not implemented.
	 * -v Display verbose output. (Optional)
	 * </pre>
	 * 
	 * -s /home/david/Documents/REU/RNA/sort_5S.txt -v -min 20 -max 20 -group 20
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		if (CommandLine.containsArg(args, "-h") >= 0) {
			output.out(helpMessage());
			output.finalizeDisplay();
			return;
		}
		int temp = CommandLine.containsArg(args, "-s");
		String sourceName = null;
		if (temp >= 0 && temp < args.length - 1) {
			sourceName = args[temp + 1];
		}
		File srcFile = new File(sourceName);
		temp = CommandLine.containsArg(args, "-d");
		boolean delete = CommandLine.containsArg(args, "-delete") >= 0;
		PriorityDeque<SortableScoredFile> list;

		if (srcFile.isDirectory())
			list = processDir(srcFile, new PriorityDeque<SortableScoredFile>());
		else
			list = processFile(srcFile, new PriorityDeque<SortableScoredFile>());

		temp = CommandLine.containsArg(args, "-min");
		if (temp >= 0 && temp < args.length - 1) {
			try {
				int quantity = Integer.parseInt(args[temp + 1]);
				if (quantity > 0) {
					List<SortableScoredFile> minList = list.getMin(quantity);
					writeListFile("minList_" + quantity + ".txt", minList);
				}
			} catch (Exception e) {
			}
		}

		temp = CommandLine.containsArg(args, "-max");
		if (temp >= 0 && temp < args.length - 1) {
			try {
				int quantity = Integer.parseInt(args[temp + 1]);
				if (quantity > 0) {
					List<SortableScoredFile> maxList = list.getMax(quantity);
					writeListFile("maxList_" + quantity + ".txt", maxList);
				}
			} catch (Exception e) {
			}
		}

		temp = CommandLine.containsArg(args, "-group");
		if (temp >= 0 && temp < args.length - 1) {
			try {
				int quantity = Integer.parseInt(args[temp + 1]);
				if (quantity > 0) {
					int i = 1;
					while (!list.isEmpty()) {
						List<SortableScoredFile> group = list.popMin(quantity);
						writeListFile("minList" + (i++) + "_" + quantity
								+ ".txt", group);
					}
				}
			} catch (Exception e) {
			}
		}

		output.console("\n\n\n\t[EXITING SortFileFormatter]");
		output.finalizeDisplay();
	}

	private static class SortableScoredFile implements Comparable<SortableScoredFile> {
		private File file;
		private double score;

		public String getAbsolutePath() {
			return file.getAbsolutePath();
		}
		
		public SortableScoredFile(File file, String score){
			this(file, Double.parseDouble(score));
		}

		public SortableScoredFile(File file, double score) {
			this.file = file;
			this.score = score;
		}

		@Override
		public int compareTo(SortableScoredFile that) {
			return (int) (this.score - that.score);
		}
	}
}
